﻿using System.Collections.Generic;
using Microsoft.Practices.Composite.Events;
using Microsoft.Practices.Unity;
using StockholmsStad.Runtime.Serialization.DataContract;
using StockholmsStad.Windows.UI.Facade;
using StockholmsStad.Windows.UI.Infrastructure.Interfaces;
using StockholmsStad.Windows.UI.Modules.Couple.Interfaces;
using StockholmsStad.Windows.UI.Modules.Couple.Models;
using StockholmsStad.Windows.UI.Modules.Couple.BusinessEntities;
using StockholmsStad.Runtime.Serialization.DataContract.Enums;
using StockholmsStad.Windows.UI.Modules.Couple.Events;
using System.Windows.Input;

namespace StockholmsStad.Windows.UI.Modules.Couple.Services
{
    public class BookingService : IBookingService
    {
        private IApplicationService applicationService;
        private readonly IEventAggregator eventAggregator;

        [Dependency]
        public IApplicationService ApplicationService
        {
            set { applicationService = value; }
        }

        public BookingService(IEventAggregator aggregator)
        {
            eventAggregator = aggregator;

        }

        #region IBookingService Members

        public BookingPresentationModel GetBooking(int ticketId)
        {
            var model = new BookingPresentationModel
                            {
                                // default 
                                CeremonyType = CeremonyType.Ordinary
                            };

            if (ticketId > 0)
            {
                var user = applicationService.GetCurrentUser();
                var facade = new BookingFacade(user);
                var booking = facade.GetBooking(ticketId);
                if (booking != null)
                {
                    model = CreateBookingModel(booking);
                }
            }

            model.TicketId = ticketId;
            model.Saved += BookingSaved;
            model.Cancelled += BookingCancelled;
            return model;
        }

        public BookingPresentationModel CopyBooking(BookingPresentationModel oldBooking)
        {
            var model = new BookingPresentationModel()
            {
                BookingId = oldBooking.BookingId,
                TicketId = oldBooking.TicketId,
                CeremonyType = oldBooking.CeremonyType,
            };

            model.Saved += BookingSaved;
            model.Cancelled += BookingCancelled;
            return model;
        }

        public List<Minister> GetMinisters()
        {
            var user = applicationService.GetCurrentUser();
            var ministerFacade = new MinisterFacade(user);
            return ministerFacade.GetMinisters();
        }

        public BookingTimeList GetFreeTimeBlocks()
        {
            var user = applicationService.GetCurrentUser();
            var bookingFacade = new BookingFacade(user);
            var timeBlocks = bookingFacade.GetFreeTimeBlocks();

            var bookings = new BookingTimeList
                               {
                                   BookingTimeBlocks = new List<BookingTimeBlock>()
                               };

            foreach(var tb in timeBlocks)
            {
                bookings.BookingTimeBlocks.Add(new BookingTimeBlock { TimeBlock = tb, Month = tb.StartDateTime.ToString("MMMM yyyy")});
            }

            return bookings;
        }

        #endregion

        #region Booking events

        private void BookingSaved(object sender, DataEventArgs<BookingPresentationModel> e)
        {
            if (e != null && e.Value != null)
            {
                Mouse.OverrideCursor = null;
                var bookingModel = e.Value;
                var booking = CreateBooking(bookingModel);
                var user = applicationService.GetCurrentUser();
                var bookingFacade = new BookingFacade(user);
                bookingFacade.SaveBooking(bookingModel.TicketId.Value, booking);

                eventAggregator.GetEvent<BookingAddedEvent>().Publish(bookingModel);

                bookingModel.IsInChangeMode = false;

            }
        }

        private void BookingCancelled(object sender, DataEventArgs<BookingPresentationModel> e)
        {
            if (e != null && e.Value != null)
            {
                Mouse.OverrideCursor = null;
                var bookingModel = e.Value;
                var user = applicationService.GetCurrentUser();
                var bookingFacade = new BookingFacade(user);
                bookingFacade.CancelBooking(bookingModel.TicketId.Value);

                eventAggregator.GetEvent<BookingCancelledEvent>().Publish(bookingModel);
            }
        }
        #endregion

        #region converter methods

        public static BookingPresentationModel CreateBookingModel(Booking booking)
        {
            var model = new BookingPresentationModel
                            {
                                BookingId = booking.BookingId,
                                CeremonyType = booking.CeremonyType,
                                BookedDate = booking.DateTime,
                                MinisterCode = booking.MinisterCode ?? string.Empty,
                            };

            if (booking.PreferredDate1 != null)
                model.PreferredDate1 = booking.PreferredDate1;

            if (booking.PreferredDate2 != null)
                model.PreferredDate2 = booking.PreferredDate2;

            return model;
        }

        public static Booking CreateBooking(BookingPresentationModel model)
        {
            var booking = new Booking
                              {
                                  CeremonyType = model.CeremonyType,
                                  DateTime = model.BookedDate,
                                  MinisterCode = model.MinisterCode,
                              };

            if (model.PreferredDate1.HasValue)
                booking.PreferredDate1 = model.PreferredDate1;

            if (model.PreferredDate2.HasValue)
                booking.PreferredDate2 = model.PreferredDate2;
            
            return booking;
        }

        #endregion
    }
}
